<template>
  <div class="js-editor">
    <h2 v-if="title && title.length > 0" class="title">{{ title }}</h2>
    <div class="content">
      <div ref="codeEditBox" class="codeEditBox"></div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { editorProps } from './monacoEditorType'
import * as monaco from 'monaco-editor'
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
const props = defineProps({
  ...editorProps,
})
const emit = defineEmits(['update:modelValue', 'change', 'editor-mounted'])

let editor: monaco.editor.IStandaloneCodeEditor
const codeEditBox = ref()
const init = () => {
  self.MonacoEnvironment = {
    getWorker(_, label) {
      if (label === 'json') {
        return new jsonWorker()
      }
      if (label === 'css' || label === 'scss' || label === 'less') {
        return new cssWorker()
      }
      if (label === 'html' || label === 'handlebars' || label === 'razor') {
        return new htmlWorker()
      }
      if (label === 'typescript' || label === 'javascript') {
        return new tsWorker()
      }
      return new editorWorker()
    },
  }
  // monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
  //   noSemanticValidation: true,
  //   noSyntaxValidation: false,
  // })
  // monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
  //   target: monaco.languages.typescript.ScriptTarget.ES2020,
  //   allowNonTsExtensions: true,
  // })
  // console.log('props.modelValue', props.modelValue)
  editor = monaco.editor.create(codeEditBox.value, {
    value: props.modelValue,
    language: props.language,
    theme: props.theme,
    ...props.options,
  }) // 监听值的变化
  // editor.setValue(editor.getValue())
  // console.log('editor', editor.getValue())
  editor.onDidChangeModelContent(() => {
    const value = editor.getValue() //给父组件实时返回最新文本
    emit('update:modelValue', value)
    emit('change', value)
  })
  emit('editor-mounted', editor)
}
watch(
  () => props.modelValue,
  (newValue) => {
    // editor.setValue(newValue)
    // console.log('modelValue', newValue)
    if (editor) {
      const value = editor.getValue()
      if (newValue !== value) {
        editor.setValue(newValue)
      }
    }
  }
)
watch(
  () => props.options,
  (newValue) => {
    editor.updateOptions(newValue)
  },
  { deep: true }
)
watch(
  () => props.language,
  (newValue) => {
    monaco.editor.setModelLanguage(editor.getModel()!, newValue)
  }
)
onBeforeUnmount(() => {
  editor.dispose()
})
onMounted(() => {
  editor?.dispose()
  init()
})
</script>

<style lang="scss" scoped>
.js-editor {
  //height: v-bind(height);
  width: 100%;
  //height: 600px;
  border: 1px solid #ccc;
  display: flex;
  flex-direction: column;
  .title {
    padding-left: 20px;
    height: 30px;
    line-height: 30px;
    font-size: 20px;
    border-bottom: 1px solid #ccc;
    font-weight: bold;
  }
  .content {
    flex: 1;
    padding: 10px;
    border: 1px solid #000;
    font-size: 14px;
  }
}
.codeEditBox {
  width: v-bind(width);
  //height: 100%;
  height: v-bind(height);
  :deep(.monaco-editor) {
    height: v-bind(height) !important;
    width: v-bind(width) !important;
    .overflow-guard {
      height: v-bind(height) !important;
      width: v-bind(width) !important;
    }
  }
}
</style>
